package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.exception.GlobalException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.StringUtils;
import com.piggy.common.core.utils.sql.SqlUtil;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.bo.LogiCarCanScheduleQueryBo;
import com.piggy.logi.sys.bo.LogiCarrierCarExtEditBo;
import com.piggy.logi.sys.bo.LogiCarrierCarQueryBo;
import com.piggy.logi.sys.domain.LogiCarrierCar;
import com.piggy.logi.sys.domain.LogiCarrierCarDriver;
import com.piggy.logi.sys.mapper.LogiCarrierCarMapper;
import com.piggy.logi.sys.service.ILogiCarrierCarDriverService;
import com.piggy.logi.sys.service.ILogiCarrierCarService;
import com.piggy.logi.sys.service.ILogiScheduleService;
import com.piggy.logi.sys.vo.LogiCarrierCarDriverExtVo;
import com.piggy.logi.sys.vo.LogiCarrierCarExtVo;
import com.piggy.logi.sys.vo.LogiScheduleVo;
import com.piggy.sys.api.RemoteDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 承运商车辆信息Service业务层处理
 */
@Slf4j
@Service
public class LogiCarrierCarServiceImpl extends ServiceImpl<LogiCarrierCarMapper, LogiCarrierCar> implements ILogiCarrierCarService {

    @Resource
    private ILogiCarrierCarDriverService logiCarrierCarDriverService;
    @Resource
    private ILogiScheduleService logiScheduleService;
    @Resource
    private RemoteDistrictService remoteDistrictService;

    @Override
    public LogiCarrierCarExtVo queryById(Long id) {
        LogiCarrierCarExtVo carrierCarVo = getVoById(id, LogiCarrierCarExtVo.class);
        if (carrierCarVo == null) {
            return null;
        }
        List<String> districtIds = Lists.newArrayList(carrierCarVo.getOwnerLocationDistrictId().toString());
        Map<String, String> districtMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();

        // 获取司机信息
        Map<Long, List<LogiCarrierCarDriverExtVo>> carDriversMap = logiCarrierCarDriverService.getCarDrivers(Lists.newArrayList(id));

        carrierCarVo.setOwnerLocationDistrictName(districtMap.get(carrierCarVo.getOwnerLocationDistrictId().toString()));
        carrierCarVo.setDriverList(carDriversMap.get(id));
        return carrierCarVo;
    }

    @Override
    public TableDataInfo<LogiCarrierCarExtVo> queryPageList(LogiCarrierCarQueryBo bo) {
        PagePlus<LogiCarrierCar, LogiCarrierCarExtVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiCarrierCarExtVo.class);

        List<LogiCarrierCarExtVo> pageListVos = result.getRecordsVo();
        fillData(pageListVos);

        result.setRecordsVo(pageListVos);
        return PageUtils.buildDataInfo(result);
    }

    private List<LogiCarrierCarExtVo> fillData(List<LogiCarrierCarExtVo> pageListVos) {
        // 获取地址数据
        List<String> districtIds = pageListVos.stream().map(item -> item.getOwnerLocationDistrictId().toString()).distinct().collect(Collectors.toList());
        Map<String, String> districtNameMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();

        // 获取司机信息
        List<Long> carIds = pageListVos.stream().map(LogiCarrierCarExtVo::getCarId).distinct().collect(Collectors.toList());
        Map<Long, List<LogiCarrierCarDriverExtVo>> carDriversMap = logiCarrierCarDriverService.getCarDrivers(carIds);

        // 获取车辆被调度信息
        List<LogiScheduleVo> scheduleVos = logiScheduleService.getByCarIds(carIds);
        Map<Long, LogiScheduleVo> scheduleVoMap = scheduleVos.stream().collect(Collectors.toMap(LogiScheduleVo::getCarId, Function.identity(), (a, b) -> a));

        pageListVos.forEach(pageListVo -> {
            pageListVo.setOwnerLocationDistrictName(districtNameMap.get(pageListVo.getOwnerLocationDistrictId().toString()));
            pageListVo.setDriverList(carDriversMap.get(pageListVo.getCarId()));
            pageListVo.setScheduleVo(scheduleVoMap.get(pageListVo.getCarId()));
        });

        return pageListVos;
    }

    @Override
    public List<LogiCarrierCarExtVo> queryList(LogiCarrierCarQueryBo bo) {
        bo.setDeptId(SecurityUtils.getDeptId());
        List<LogiCarrierCarExtVo> carrierCarExtVos = listVo(buildQueryWrapper(bo), LogiCarrierCarExtVo.class);

        fillData(carrierCarExtVos);

        return carrierCarExtVos;
    }

    private LambdaQueryWrapper<LogiCarrierCar> buildQueryWrapper(LogiCarrierCarQueryBo bo) {
        LambdaQueryWrapper<LogiCarrierCar> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getLicensePlate() != null, LogiCarrierCar::getLicensePlate, bo.getLicensePlate());
        lqw.eq(bo.getHeadType() != null, LogiCarrierCar::getHeadType, bo.getHeadType());
        lqw.eq(bo.getCarType() != null, LogiCarrierCar::getCarType, bo.getCarType());
        lqw.eq(bo.getOwnerLocationDistrictId() != null, LogiCarrierCar::getOwnerLocationDistrictId, bo.getOwnerLocationDistrictId());
        if (StringUtils.isNotBlank(bo.getCreateTimeStr())) {
            lqw.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", bo.getCreateTimeStr());
        }
        // 部门数据权限过滤
        if (ObjectUtil.isNotNull(bo.getDeptId())) {
            SqlUtil.dataPermissionFilter(lqw, bo.getDeptId());
        }
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByAddBo(LogiCarrierCarExtEditBo bo) {
        LogiCarrierCar add = BeanUtil.toBean(bo, LogiCarrierCar.class);
        LogiCarrierCar logiCarrierCar = baseMapper.findByUk(bo.getMainDeptId(), bo.getLicensePlate());
        if (logiCarrierCar != null) {
            throw new GlobalException("当前车牌号已存在");
        }
        boolean ret = save(add);
        // 关联司机信息
        if (CollUtil.isEmpty(bo.getDriverList())) {
            return ret;
        }
        List<LogiCarrierCarDriver> carrierDriverList = Lists.newArrayList();
        bo.getDriverList().forEach(driverVo -> {
            LogiCarrierCarDriver carrierDriver = new LogiCarrierCarDriver();
            carrierDriver.setDeptId(add.getDeptId());
            carrierDriver.setCarId(add.getCarId());
            carrierDriver.setDriverId(driverVo.getDriverId());
            carrierDriver.setMainDriver(driverVo.getMainDriver());
            carrierDriverList.add(carrierDriver);
        });
        logiCarrierCarDriverService.saveBatch(carrierDriverList);

        return ret;
    }

    @Override
    public Boolean updateByEditBo(LogiCarrierCarExtEditBo bo) {
        if (bo.getCarId() == null) {
            throw new GlobalException("修改ID不能为空");
        }
        LogiCarrierCar logiCarrierCarDb = baseMapper.selectById(bo.getCarId());
        if (logiCarrierCarDb == null) {
            throw new GlobalException("数据不存在");
        }
        if (StrUtil.isNotBlank(bo.getLicensePlate())) {
            LogiCarrierCar logiCarrierCarUK = baseMapper.findByUk(bo.getMainDeptId(), bo.getLicensePlate());
            if (ObjectUtil.isNotEmpty(logiCarrierCarUK) && !Objects.equals(logiCarrierCarUK.getCarId(), logiCarrierCarDb.getCarId())) {
                throw new GlobalException("当前车牌号已存在");
            }
        }

        LogiCarrierCar update = BeanUtil.toBean(bo, LogiCarrierCar.class);

        if (CollUtil.isNotEmpty(bo.getDriverList())) {
            bo.getDriverList().forEach(driverEditBo -> {
                driverEditBo.setCarId(bo.getCarId());
            });
        }
        logiCarrierCarDriverService.updateCarDriver(bo.getCarId(), bo.getDriverList());
        return updateById(update);
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            if (CollUtil.isEmpty(ids)) {
                throw new GlobalException("修改ID不能为空");
            }
        }
        return removeByIds(ids);
    }

    @Override
    public LogiCarrierCarExtVo queryByLicensePlate(Long deptId, String licensePlate) {
        LogiCarrierCar carrierCar = baseMapper.selectOne(Wrappers.<LogiCarrierCar>lambdaQuery()
                //.eq(LogiCarrierCar::getDeptId, deptId)
                .apply(SqlUtil.getDataPermissionSql(deptId))
                .eq(LogiCarrierCar::getLicensePlate, licensePlate));
        LogiCarrierCarExtVo carrierCarVo = BeanUtil.toBean(carrierCar, LogiCarrierCarExtVo.class);
        if (carrierCarVo == null) {
            return null;
        }
        List<String> districtIds = Lists.newArrayList(carrierCarVo.getOwnerLocationDistrictId().toString());
        Map<String, String> districtMap = remoteDistrictService.getDistrictMap(districtIds, SecurityConstants.INNER).getData();

        // 获取司机信息
        Map<Long, List<LogiCarrierCarDriverExtVo>> carDriversMap = logiCarrierCarDriverService.getCarDrivers(Lists.newArrayList(carrierCar.getCarId()));

        carrierCarVo.setOwnerLocationDistrictName(districtMap.get(carrierCarVo.getOwnerLocationDistrictId().toString()));
        carrierCarVo.setDriverList(carDriversMap.get(carrierCar.getCarId()));
        return carrierCarVo;
    }

    @Override
    public List<LogiCarrierCarExtVo> canScheduleList(LogiCarCanScheduleQueryBo bo) {
        return fillData(baseMapper.canScheduleList(bo));
    }

}
